﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;

using Microsoft.Coding4Fun.TweetCraft.Targa;

namespace Microsoft.Coding4Fun.TweetCraft.Twitter
{
    /// <summary>
    /// Provides a class to convert Twitter user pictures to Targa files using a destination width and height pair
    /// and can also enlarge the canvas to a larger size.
    /// </summary>
    public class GdiPlusTargaConverter : UserPictureConverter
    {
        public GdiPlusTargaConverter(int destinationWidth, int destinationHeight, int enlargedDestinationWidth, int enlargedDestinationHeight) : base(destinationWidth, destinationHeight, enlargedDestinationWidth, enlargedDestinationHeight)
        {
        }

        public GdiPlusTargaConverter(int destinationWidth, int destinationHeight) : base(destinationWidth, destinationHeight)
        {
        }

        /// <summary>
        /// Converts a Twitter user picture to a Targa file.
        /// </summary>
        /// <param name="source">The path to the source file.</param>
        /// <param name="destination">The path to the destination Targa file.</param>
        /// <returns>
        /// True, if the conversion was successful; false otherwise.
        /// </returns>
        public override bool Convert(string source, string destination)
        {
            if (source == null)
                throw new ArgumentNullException("source");
            if (destination == null)
                throw new ArgumentNullException("destination");
            if (!File.Exists(source))
                throw new ArgumentException(Strings.SourceImageDoesNotExist, "source");

            using (TraceScope scope = TraceScope.Information("Converting user picture using GDI+..."))
            {
                try
                {
                    // Load the image from the file
                    using (var sourceBitmap = (Bitmap)Image.FromFile(source))
                    {
                        Trace.TraceInformation("Source Width = {0}, Height = {1}, PixelFormat = {2}", sourceBitmap.Width, sourceBitmap.Height,  sourceBitmap.PixelFormat);

                        // Initialize a 64x64 pixel bitmap
                        using (var userPictureBitmap = new Bitmap(EnlargedDestinationWidth, EnlargedDestinationHeight))
                        {
                            // Initialize a Graphics context for the user picture bitmap
                            using (Graphics graphics = Graphics.FromImage(userPictureBitmap))
                            {
                                // Calculate the rectangle where the user picture will reside
                                var destinationPoint = new Point((EnlargedDestinationWidth - DestinationWidth) / 2, (EnlargedDestinationHeight - DestinationHeight) / 2);
                                var destinationRectangle = new Rectangle(destinationPoint, new Size(DestinationWidth, DestinationHeight));

                                // Draw the source bitmap into the middle of the user picture bitmap
                                graphics.DrawImage(sourceBitmap, destinationRectangle);
                            }

                            Trace.TraceInformation("User picture has been resized to {0}x{1} and drawn onto a {2}x{3} canvas.", DestinationWidth, DestinationHeight, EnlargedDestinationWidth, EnlargedDestinationHeight);

                            try
                            {
                                // Save the image to the destination
                                userPictureBitmap.SaveTarga(destination);

                                scope.Complete("User picture conversion complete, user picture saved.");

                                // Conversion was successful, return true
                                return true;
                            }
                            catch (ExternalException)
                            {
                                /* The image was saved with the wrong image format.
                                   -or- 
                                   The image was saved to the same file it was created from.
                                 */
                                Trace.TraceError("Could not save user picture.");

                                return false;
                            }
                        }
                    }
                }
                catch (OutOfMemoryException)
                {
                    /* The file does not have a valid image format.
                       -or-
                       GDI+ does not support the pixel format of the file.
                     */

                    Trace.TraceError("Could not load user picture.");

                    return false;
                }
            }
        }
    }
}